<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Go by Example 中文版: 生成进程</title>
    <link rel=stylesheet href="site.css">
  </head>
  <script>
      onkeydown = (e) => {
          
          if (e.key == "ArrowLeft") {
              window.location.href = 'context';
          }
          
          
          if (e.key == "ArrowRight") {
              window.location.href = 'execing-processes';
          }
          
      }
  </script>
  <body>

    <div class="example" id="spawning-processes">
      <h2><a href="./">Go by Example 中文版</a>: 生成进程</h2>
      
      <table>
        
        <tr>
          <td class="docs">
            <p>有时，我们的 Go 程序需要生成其他的、非 Go 的进程。
例如，这个网站的语法高亮是通过在 Go 程序中生成一个 <a href="http://pygments.org/"><code>pygmentize</code></a>
来<a href="https://github.com/everyx/gobyexample/blob/master/tools/generate.go">实现的</a>。
让我们看一些关于 Go 生成进程的例子。</p>

          </td>
          <td class="code empty leading">
            
          
          </td>
        </tr>
        
        <tr>
          <td class="docs">
            
          </td>
          <td class="code leading">
            <a href="http://play.golang.org/p/k1lKqPRe5ER"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
          <div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            
          </td>
          <td class="code leading">
            
          <div class="highlight"><pre><span class="kn">import</span> <span class="p">(</span>
    <span class="s">&quot;fmt&quot;</span>
    <span class="s">&quot;io/ioutil&quot;</span>
    <span class="s">&quot;os/exec&quot;</span>
<span class="p">)</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            
          </td>
          <td class="code leading">
            
          <div class="highlight"><pre><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p>我们将从一个简单的命令开始，没有参数或者输入，仅打印一些信息到标准输出流。
<code>exec.Command</code> 可以帮助我们创建一个对象，来表示这个外部进程。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre>    <span class="nx">dateCmd</span> <span class="o">:=</span> <span class="nx">exec</span><span class="p">.</span><span class="nx">Command</span><span class="p">(</span><span class="s">&quot;date&quot;</span><span class="p">)</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p><code>.Output</code> 是另一个帮助函数，常用于处理运行命令、等待命令完成并收集其输出。
如果没有错误，<code>dateOut</code> 将保存带有日期信息的字节。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre>    <span class="nx">dateOut</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">dateCmd</span><span class="p">.</span><span class="nx">Output</span><span class="p">()</span>
    <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
        <span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;&gt; date&quot;</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">dateOut</span><span class="p">))</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p>下面我们将看看一个稍复杂的例子，
我们将从外部进程的 <code>stdin</code> 输入数据并从 <code>stdout</code> 收集结果。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre>    <span class="nx">grepCmd</span> <span class="o">:=</span> <span class="nx">exec</span><span class="p">.</span><span class="nx">Command</span><span class="p">(</span><span class="s">&quot;grep&quot;</span><span class="p">,</span> <span class="s">&quot;hello&quot;</span><span class="p">)</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p>这里我们明确的获取输入/输出管道，运行这个进程，
写入一些输入数据、读取输出结果，最后等待程序运行结束。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre>    <span class="nx">grepIn</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">grepCmd</span><span class="p">.</span><span class="nx">StdinPipe</span><span class="p">()</span>
    <span class="nx">grepOut</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">grepCmd</span><span class="p">.</span><span class="nx">StdoutPipe</span><span class="p">()</span>
    <span class="nx">grepCmd</span><span class="p">.</span><span class="nx">Start</span><span class="p">()</span>
    <span class="nx">grepIn</span><span class="p">.</span><span class="nx">Write</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="s">&quot;hello grep\ngoodbye grep&quot;</span><span class="p">))</span>
    <span class="nx">grepIn</span><span class="p">.</span><span class="nx">Close</span><span class="p">()</span>
    <span class="nx">grepBytes</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">ioutil</span><span class="p">.</span><span class="nx">ReadAll</span><span class="p">(</span><span class="nx">grepOut</span><span class="p">)</span>
    <span class="nx">grepCmd</span><span class="p">.</span><span class="nx">Wait</span><span class="p">()</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p>上面的例子中，我们忽略了错误检测，
当然，你也可以使用常见的 <code>if err != nil</code> 方式来进行错误检查。
我们只收集了 <code>StdoutPipe</code> 的结果，
但是你可以使用相同的方法收集 <code>StderrPipe</code> 的结果。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;&gt; grep hello&quot;</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">grepBytes</span><span class="p">))</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            <p>注意，在生成命令时，我们需要提供一个明确描述命令和参数的数组，而不能只传递一个命令行字符串。
如果你想使用一个字符串生成一个完整的命令，那么你可以使用 <code>bash</code> 命令的 <code>-c</code> 选项：</p>

          </td>
          <td class="code">
            
          <div class="highlight"><pre>    <span class="nx">lsCmd</span> <span class="o">:=</span> <span class="nx">exec</span><span class="p">.</span><span class="nx">Command</span><span class="p">(</span><span class="s">&quot;bash&quot;</span><span class="p">,</span> <span class="s">&quot;-c&quot;</span><span class="p">,</span> <span class="s">&quot;ls -a -l -h&quot;</span><span class="p">)</span>
    <span class="nx">lsOut</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">lsCmd</span><span class="p">.</span><span class="nx">Output</span><span class="p">()</span>
    <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
        <span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;&gt; ls -a -l -h&quot;</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">lsOut</span><span class="p">))</span>
<span class="p">}</span>
</pre></div>

          </td>
        </tr>
        
      </table>
      
      <table>
        
        <tr>
          <td class="docs">
            <p>生成的程序返回的输出，和我们直接通过命令行运行这些程序的输出是相同的。</p>

          </td>
          <td class="code leading">
            
          <div class="highlight"><pre><span class="gp">$</span> go run spawning-processes.go 
<span class="gp">&gt;</span> date
<span class="go">Wed Oct 10 09:53:11 PDT 2012</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            
          </td>
          <td class="code leading">
            
          <div class="highlight"><pre><span class="gp">&gt;</span> grep hello
<span class="go">hello grep</span>
</pre></div>

          </td>
        </tr>
        
        <tr>
          <td class="docs">
            
          </td>
          <td class="code">
            
          <div class="highlight"><pre><span class="gp">&gt;</span> ls -a -l -h
<span class="go">drwxr-xr-x  4 mark 136B Oct 3 16:29 .</span>
<span class="go">drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..</span>
<span class="go">-rw-r--r--  1 mark 1.3K Oct 3 16:28 spawning-processes.go</span>
</pre></div>

          </td>
        </tr>
        
      </table>
      
      
      <p class="next">
        下一个例子: <a href="execing-processes">执行进程</a>
      </p>
      
      <p class="footer">
        <a href="https://twitter.com/mmcgrana">@mmcgrana</a> 编写 | <a href="https://github.com/gobyexample-cn">gobyexample-cn</a> 翻译 | <a href="https://github.com/gobyexample-cn/gobyexample/issues">反馈</a> | <a href="https://github.com/gobyexample-cn/gobyexample">源码</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>      </p>
      </p>
    </div>
    <script>
      var codeLines = [];
      codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A    \"fmt\"\u000A    \"io/ioutil\"\u000A    \"os/exec\"\u000A)\u000A');codeLines.push('func main() {\u000A');codeLines.push('    dateCmd := exec.Command(\"date\")\u000A');codeLines.push('    dateOut, err := dateCmd.Output()\u000A    if err != nil {\u000A        panic(err)\u000A    }\u000A    fmt.Println(\"\x3E date\")\u000A    fmt.Println(string(dateOut))\u000A');codeLines.push('    grepCmd := exec.Command(\"grep\", \"hello\")\u000A');codeLines.push('    grepIn, _ := grepCmd.StdinPipe()\u000A    grepOut, _ := grepCmd.StdoutPipe()\u000A    grepCmd.Start()\u000A    grepIn.Write([]byte(\"hello grep\\ngoodbye grep\"))\u000A    grepIn.Close()\u000A    grepBytes, _ := ioutil.ReadAll(grepOut)\u000A    grepCmd.Wait()\u000A');codeLines.push('    fmt.Println(\"\x3E grep hello\")\u000A    fmt.Println(string(grepBytes))\u000A');codeLines.push('    lsCmd := exec.Command(\"bash\", \"-c\", \"ls -a -l -h\")\u000A    lsOut, err := lsCmd.Output()\u000A    if err != nil {\u000A        panic(err)\u000A    }\u000A    fmt.Println(\"\x3E ls -a -l -h\")\u000A    fmt.Println(string(lsOut))\u000A}\u000A');codeLines.push('');codeLines.push('');codeLines.push('');
    </script>
    <script src="site.js" async></script>
  </body>
</html>
